package admin.data;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;

import search.DealSearchEngine;

import models.DealModel;
import models.ProductModel;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyOpts;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;

import debugs.DealDebug;

public class DealData {

	private static Objectify ofy;

	private static Cache cache = null;

	private static boolean isRegisted = false;

	private static ObjectifyOpts opts = null;

	private static String prefix = "dealData_";

	private int limit = 20;

	private int page = 1;

	private int totalResult = 0;

	private List<DealModel> listResult = new ArrayList<DealModel>();

	public List<DealModel> getListResult() {
		return listResult;
	}

	public int getLimit() {
		return limit;
	}

	public void setLimit(int limit) {
		this.limit = limit;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public boolean isHasNextPage() {
		if (totalResult != 0) {
			return totalResult > (page * limit);
		} else {
			return false;
		}
	}

	public boolean isHasPreviousPage() {
		return page > 1;
	}

	public DealData() {
		init();
	}

	public static void init() {
		if (!isRegisted) {
			try {
				ObjectifyService.register(DealModel.class);
			} catch (Exception e) {

			}
			try {
				cache = CacheManager.getInstance().getCacheFactory()
						.createCache(Collections.emptyMap());
			} catch (CacheException e) {

			}
			opts = new ObjectifyOpts().setSessionCache(true);
			isRegisted = true;
		}
		ofy = ObjectifyService.begin(opts);
	}

	public void prepareList() {
		listResult = new ArrayList<DealModel>();
		int start = (page - 1) * limit;
		Query<DealModel> q = ofy.query(DealModel.class);
		totalResult = q.count();
		q = q.limit(limit).offset(start);
		for (DealModel deal : q) {
			listResult.add(deal);
		}
	}

	public void getByCity(String city) {
		listResult = new ArrayList<DealModel>();
		int start = (page - 1) * limit;
		Query<DealModel> q = ofy.query(DealModel.class)
				.filter("endDate >", city).filter("city", city).limit(limit)
				.offset(start);
		totalResult = q.count();
		for (DealModel deal : q) {
			listResult.add(deal);
		}
	}

	public void getByCityAndCategory(String cityId, String categoryId) {
		listResult = new ArrayList<DealModel>();
		int start = (page - 1) * limit;
		Query<DealModel> q = ofy.query(DealModel.class).filter("city", cityId)
				.filter("category", categoryId).limit(limit).offset(start);
		totalResult = q.count();
		for (DealModel deal : q) {
			listResult.add(deal);
		}
	}

	@SuppressWarnings("unchecked")
	public static void insert(DealModel deal) {
		init();
		if (cache != null) {
			cache.put(prefix + deal.getDealId(), deal);
		}
		ofy.put(deal);
		DealSearchEngine.update(deal);
	}

	@SuppressWarnings("unchecked")
	public static void insert(DealModel deal, List<ProductModel> listProduct) {
		init();
		if (cache != null) {
			cache.put(prefix + deal.getDealId(), deal);
		}
		ofy.put(deal);
		if (listProduct != null && listProduct.size() > 0) {
			try {
				for (ProductModel productModel : listProduct) {
					productModel.setDealId(deal.getDealId());
					productModel.setDealName(deal.getShortName());
					ProductData.insert(productModel);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		DealSearchEngine.update(deal);
	}

	public static void delete(DealModel deal) {
		init();
		if (cache != null && cache.containsKey(prefix + deal.getDealId())) {
			cache.remove(prefix + deal.getDealId());
		}
		ofy.delete(deal);
		DealSearchEngine.remove(deal.getDealId());
	}

	@SuppressWarnings("unchecked")
	public static DealModel getById(String id) {
		init();
		DealModel deal = new DealModel();
		if (cache != null && cache.containsKey(prefix + id)) {
			deal = (DealModel) cache.get(prefix + id);
		} else {
			try {
				deal = ofy.get(new Key<DealModel>(DealModel.class, id));
				cache.put(prefix + id, deal);
			} catch (Exception e) {
				deal = null;
			}
		}
		return deal;
	}

	public static DealModel getDealMarketing(String cityId, String categoryId) {
		init();
		DealModel deal = new DealModel();
		Query<DealModel> q = ofy.query(DealModel.class)
				.filter("endTime >", Calendar.getInstance().getTime())
				.filter("city", cityId).filter("dealType", 1)
				.filter("status", 2);
		if (cityId != null && !cityId.isEmpty()) {
			q = q.filter("city", cityId);
		}
		if (categoryId != null && !categoryId.isEmpty()
				&& !categoryId.equals("all")) {
			q = q.filter("category", categoryId);
		}
		List<DealModel> list = new ArrayList<DealModel>();
		for (DealModel dealModel : q) {
			list.add(dealModel);
		}
		Collections.sort(list);
		if (list.size() > 0)
			deal = list.get(0);		
		return deal;
	}

	@SuppressWarnings("unchecked")
	public static DealModel getActiveById(String id) {
		init();
		DealModel deal = new DealModel();
		if (cache != null && cache.containsKey(prefix + id)) {
			deal = (DealModel) cache.get(prefix + id);
		} else {
			try {
				deal = ofy.get(new Key<DealModel>(DealModel.class, id));
				cache.put(prefix + id, deal);
			} catch (Exception e) {
				deal = null;
			}
		}
		if (deal.getStatus() == 2) {
			return deal;
		} else {
			return null;
		}
	}

	public ArrayList<DealModel> getByListId(List<String> ids) {
		ArrayList<DealModel> deals = new ArrayList<DealModel>();
		Map<String, DealModel> lst = ofy.get(DealModel.class, ids);
		for (int i = 0; i < ids.size(); i++) {
			deals.add(lst.get(ids.get(i)));
		}
		return deals;
	}

	public ArrayList<DealModel> getAll() {
		ArrayList<DealModel> deals = new ArrayList<DealModel>();
		// Get all key
		Iterable<Key<DealModel>> allKeys = ofy.query(DealModel.class)
				.fetchKeys();

		Map<Key<DealModel>, DealModel> lst = ofy.get(allKeys);

		for (Map.Entry<Key<DealModel>, DealModel> entry : lst.entrySet()) {
			deals.add(entry.getValue());
		}

		return deals;
	}

	public ArrayList<DealModel> getDealActive() {
		ArrayList<DealModel> deals = new ArrayList<DealModel>();
		Query<DealModel> q = ofy.query(DealModel.class)
				.filter("startTime <=", Calendar.getInstance().getTime())
				.filter("status", 1);

		for (DealModel deal : q) {
			DealDebug.debug(deal);
		}
		return deals;
	}

	public ArrayList<DealModel> getDealRunning() {
		ArrayList<DealModel> deals = new ArrayList<DealModel>();
		Query<DealModel> q = ofy.query(DealModel.class)
				.filter("endTime <=", Calendar.getInstance().getTime())
				.filter("status", 2);

		for (DealModel deal : q) {
			deals.add(deal);
		}
		return deals;
	}
}
